package com.lwl.mini.reflection;

import com.lwl.mini.binding.BindingException;
import com.lwl.mini.builder.annotation.Param;

import java.io.Reader;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * @author lwl
 * @create 2022/4/16 10:34
 */
public class ParamNameResolver {

    /**
     * 有序set
     */
    private Set<String> paramSet = new TreeSet<>(new Comparator<String>() {
        @Override
        public int compare(String o1, String o2) {
            return o1.hashCode()-o2.hashCode();
        }
    });

    SetArray<String> setArray = new SetArray<>();

    public ParamNameResolver(Method method) {
        //读取参数列表中使用了@param命名的参数
        for(Parameter param:method.getParameters()){
            Param annotation = param.getAnnotation(Param.class);
            if(annotation == null){
                throw new BindingException("执行方法需要在参数列表加上@param注释，为参数命名");
            }
            String value = annotation.value();
            if(paramSet.contains(value)){
                throw new BindingException("@param命名重复，请修改");
            }
            setArray.push(value);
         //   paramSet.add(value);
        }
    }

    /**
     * @return Map<String,String>, key为@param注解配置的参数名，value为参数值
     */
    public Map<Object,Object> getNamedParams(Object[] args){
        //CAS
        AtomicInteger index = new AtomicInteger(0);
        Map<Object,Object> map = setArray.getArr().stream().collect(HashMap::new,(k,v)->k.put(v,args[index.getAndIncrement()]),HashMap::putAll);
        return map;
    }

    /**
     * 具有去重特性的Array数组
     */
    class SetArray<T>{

        List<T> arr = new ArrayList<>();

        public void push(T value){
            if(arr.contains(value)){
                throw new BindingException("请勿给参数赋重复名");
            }
            arr.add(value);
        }

        public T get(int index){
            return arr.get(index);
        }

        public List<T> getArr(){
            return arr;
        }
    }
}
